package gov.nasa.anml.lifted;

import java.util.ArrayList;

import gov.nasa.anml.PDDL;
import gov.nasa.anml.State;
import gov.nasa.anml.PDDL.CompoundEffect;
import gov.nasa.anml.PDDL.Time;
import gov.nasa.anml.utility.SimpleBoolean;
import static gov.nasa.anml.lifted.ANMLBoolean.*;

public class WhenStatement implements Statement, StatementContainer {
	public Expression<SimpleBoolean,?> guard;
	public Statement sThen;
	
	public boolean apply(State p, int contextID,State c) {
		if (guard.value(p)==True)
			return sThen.apply(p,contextID,c);
		return true;
	}
	
	public WhenStatement(Expression<SimpleBoolean,?> guard,Statement sThen) {
		super();
		this.guard = guard;
		this.sThen = sThen;
	}
	
	public Statement addStatement(Statement s) {
		if (sThen == null)
			return sThen = s;
		return null;
	}

	public void translateDecl(PDDL pddl, Interval unit) {
		guard.translateDecl(pddl,unit);
		sThen.translateDecl(pddl,unit);
	}
	
	public void translateStmt(PDDL pddl, Interval unit, Time part) {
		ArrayList<PDDL.BooleanExpression> conditions = unit.getPDDLConditions(); 
		ArrayList<PDDL.Effect> effects = unit.getPDDLEffects();
		
		IntervalImp iThen = new IntervalImp(unit);
		iThen.copyPDDL(unit);
		iThen.pddlConditions = new ArrayList<PDDL.BooleanExpression>();
		iThen.pddlEffects = new ArrayList<PDDL.Effect>();

		guard.translateStmt(pddl,iThen,part);
		
		PDDL.BooleanExpression head; 
		if (iThen.pddlConditions.size() == 1) {
			head = iThen.pddlConditions.get(0);
			iThen.pddlConditions.clear();
		} else {
			// this takes control of the entire array iThen.pddlConditions
			head = pddl.wrap(PDDL.Op.and,iThen.pddlConditions);
			// so we need a new array -- calling .clear() would really muck things up.
			iThen.pddlConditions = new ArrayList<PDDL.BooleanExpression>();
		}
		
		// this probably shouldn't happen; it would mean side-effects in the guard evaluation
		unit.getPDDLEffects().addAll(iThen.pddlEffects);
		iThen.pddlEffects.clear();
		
		sThen.translateStmt(pddl,iThen,part);
		
		switch(iThen.pddlConditions.size()) {
		case 0:
			break;
		case 1:
			conditions.add(pddl.makeTest(PDDL.Op.implies,head,iThen.pddlConditions.get(0)));
			break;
		default:
			conditions.add(pddl.makeTest(PDDL.Op.implies,head,pddl.wrap(PDDL.Op.and,iThen.pddlConditions)));
		}
		switch(iThen.pddlEffects.size()) {
		case 0:
			break;
		case 1:
			effects.add(pddl.new ConditionalEffect(head,iThen.pddlEffects.get(0)));
			break;
		default:
			effects.add(pddl.new ConditionalEffect(head,pddl.wrap(PDDL.Op.and,iThen.pddlEffects)));
		}
		/*
		head = pddl.wrap(PDDL.Op.not,head);
		
		Interval iElse = new Interval(unit);
		iElse.copyPDDL(unit);
		iElse.pddlConditions = new ArrayList<PDDL.BooleanExpression>();
		iElse.pddlEffects = new ArrayList<PDDL.Effect>();
		sElse.translateStmt(pddl,iElse,part);
		
		switch(iElse.pddlConditions.size()) {
		case 0:
			break;
		case 1:
			conditions.add(pddl.wrap(PDDL.Op.imply,head,iElse.pddlConditions.get(0)));
			break;
		default:
			conditions.add(pddl.wrap(PDDL.Op.imply,head,pddl.wrap(PDDL.Op.and,iElse.pddlConditions)));
		}
		switch(iElse.pddlEffects.size()) {
		case 0:
			break;
		case 1:
			effects.add(pddl.new ConditionalEffect(head,iElse.pddlEffects.get(0)));
			break;
		default:
			effects.add(pddl.new ConditionalEffect(head,pddl.wrap(PDDL.Op.and,iElse.pddlEffects)));
		}
		 */		
	}

}
